package com.lq.learningTest.File.BigWork;

import java.io.*;
import java.util.*;

public class Shop {
    //把输入对象搞成饿汉式，一运行程序就需要你输入内容
    private static Scanner scanner = new Scanner(System.in);

    //静态常量读写的文件
    public static final String PATH = "C:\\Users\\17675\\Desktop\\javaAll\\javaSE\\testDemo\\com\\lq\\learningTest\\File\\BigWork\\Shop.txt";

    public static void main(String[] args) throws IOException {

        while (true) {
            System.out.println("请选择功能：1、插入新商品 2、删除商品 3、修改商品 4、查看商品 4、查看一个商品 5、退出");
            int function = scanner.nextInt();
            switch (function){
                case 1:
                    insert();
                    break;
                case 2:
                    delete();
                    break;
                case 3:
                    update();
                    break;
                case 4:
                    check();
                    break;
                case 5:
                    findOne();
                    break;
                case 6:
                    System.exit(-1);
                    break;
            }
        }
    }

    private static void findOne() throws IOException {
        System.out.println("请输入商品编号：");
        int id = scanner.nextInt();
        // 函数式编程找到对应id的商品,流水线Stream上找到第一个就返回对象，没有则为空Optional
        Optional<Goods> first = findAllGoods().stream().filter(g -> g.getId() == id).findFirst();
        if (first.isPresent()){
            Goods goods = first.get();
            System.out.println(goods.getId() + " " + goods.getName() + " " + goods.getPrice());
        } else {
            System.out.println("您需要的商品不存在");
        }
    }

    private static void check() throws IOException {
        List<Goods> allGoods = findAllGoods();
        //增强for循环遍历
        for (Goods goods : allGoods) {
            System.out.println(goods.getId() + " " + goods.getName() + " " + goods.getPrice());
        }
    }

    private static void update() throws IOException {
        // 输入商品id
        System.out.println("请输入商品编号：");
        int id = scanner.nextInt();
        System.out.println("请输入商品名字：");
        String name = scanner.next();
        System.out.println("请输入商品价格：");
        int price = scanner.nextInt();
        // 内存中删除对应的商品
        List<Goods> allGoods = findAllGoods();
        Iterator<Goods> iterator = allGoods.iterator();
        while (iterator.hasNext()){
            Goods goods = iterator.next();
            if(goods.getId() == id){
                goods.setName(name);
                goods.setPrice(price);
            }
        }

        // 刷入磁盘，覆盖原来的内容
        writeGoods(allGoods,false);
    }

    private static void delete() throws IOException {
        // 输入商品id
        System.out.println("请输入商品编号：");
        int id = scanner.nextInt();
        // 内存中删除对应的商品
        List<Goods> allGoods = findAllGoods();
        Iterator<Goods> iterator = allGoods.iterator();
        //使用迭代器加while循环来删除
        while (iterator.hasNext()){
            Goods goods = iterator.next();
            if(goods.getId() == id){
                iterator.remove();
            }
        }

        // 刷入磁盘，这里是false就是覆盖原来的内容，而不是追加
        writeGoods(allGoods,false);
    }

    private static void insert() throws IOException {
        // 防止id重复
        boolean flag = true;
        Integer id = null;
        while (flag) {
            System.out.println("请输入商品编号：");
            id = scanner.nextInt();
            final Integer i = id;

            //把查询到的集合所有内容放到流水线上处理（Stream编程：前-中-后）
            //使用类型为Optional,拿到的这个值是“可能为空”的，需要检查它是否存在，而不能直接使用,避免空指针异常，
            // 即使没有找到元素，也不会返回 null，而是一个空的 Optional 实例
            Optional<Goods> first = findAllGoods().stream().filter(p -> p.getId() == i).findFirst();//返回流中第一个符合条件的元素
            flag = first.isPresent();
            if (flag) {
                System.out.println("该编号已经存在！");
            }
        }

        System.out.println("请输入商品名字：");
        String name = scanner.next();
        System.out.println("请输入商品价格：");
        int price = scanner.nextInt();
        // 最简单，直接追加，必须加true,不加就是覆盖
        //这里不同模块之间的数据交流使用集合来处理
        writeGoods(Arrays.asList(new Goods(id,name,price)),true);
    }

    /**
     * 从磁盘中获取所有的数据
     * @return
     */
    private static List<Goods> findAllGoods() throws IOException {
        //查询到的文件内容放在ArrayList集合中，每个元素是Goods对象
        List<Goods> goodsList = new ArrayList<>();

        /*
        在 Java 中，try () {} 这种写法是 Java 7 引入的 try-with-resources 语法，用于自动关闭资源。
        其核心作用是：确保在 try 块执行完毕后，自动关闭括号中声明的资源（如文件、网络连接、数据库连接等），
        无需手动调用 close() 方法，也不用写 finally 块。
         */
        //字符输入流访问文件
        try (Reader reader = new FileReader(Shop.PATH);//节点流
             BufferedReader bufferedReader = new BufferedReader(reader);//处理流，内存缓存
        ){
            String goodsStr;
            while ((goodsStr = bufferedReader.readLine()) != null){
                // 1 肥皂 23
                String[] goodsElem = goodsStr.split(" ");
                Goods goods = new Goods(
                        Integer.parseInt(goodsElem[0]),
                        goodsElem[1],
                        Integer.parseInt(goodsElem[2]));
                goodsList.add(goods);
            }
        } catch (IOException e){
            e.printStackTrace();
        }
        return goodsList;
    }

    private static void writeGoods(List<Goods> allGoods,boolean append){
        //节点流追加内容
        try( Writer writer = new FileWriter(Shop.PATH,append);//节点流
             BufferedWriter bufferedWriter = new BufferedWriter(writer);//处理流
        ) {//增强for循环遍历集合中的所有对象进行写入，其实这里每次插入不是批量插入，就只有一个元素
            for (Goods goods : allGoods) {
                bufferedWriter.write(goods.getId() + " " + goods.getName() + " " + goods.getPrice());
                bufferedWriter.newLine();//换行操作
            }
        } catch (IOException e){
            e.printStackTrace();
        }
    }

    private static class Goods{
        private int id;
        private String name;
        private int price;

        public Goods() {
        }

        public Goods(int id, String name, int price) {
            this.id = id;
            this.name = name;
            this.price = price;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getPrice() {
            return price;
        }

        public void setPrice(int price) {
            this.price = price;
        }

        @Override
        public String toString() {
            return "Goods{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", price=" + price +
                    '}';
        }
    }
}
